package cn.com.dhcc.turbo.dao.registry;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import cn.com.dhcc.app.core.CM;
import cn.com.dhcc.app.core.dao.AbstractCrudDao;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.handler.modulehandler.ModuleFeatureBeanRowWapper;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.util.JsonUtil;
import cn.com.dhcc.app.pub.core.consts.TlqConfig;
import cn.com.dhcc.turbo.entity.registry.NodePipeline;
import cn.com.dhcc.turbo.entity.registry.PipelineRegion;
import cn.com.dhcc.turbo.service.queue.tlq.TlqCache;
import cn.com.dhcc.turbo.service.registry.vo.PipeLineTlq;

/**
 * 
 * 传输通道dao
 * 
 * @日期：2014-5-20 下午2:11:15
 * @作者：张洪涛
 * @版权所有：东华软件
 * @版本：1.0
 */
@Repository
public class PipelineRegionDao extends AbstractCrudDao<PipelineRegion> {
	@SuppressWarnings("deprecation")
	private static Logger logger = Log.getExistLogger(LOGTYPE.SAI);

	@Autowired
	NodePipelineDao nodePipelineDao;
	
	/**
	 * 根据一个节点信息获取通道信息
	 * @param nodecode
	 * @return
	 */
	public NodePipeline getNodePieline(String nodecode) throws DaoException {
		String sql="select * from "+SI_TABLE("turbo_node_pipeline")+" where id=(select PIPELINE_ID from "+SI_TABLE("turbo_pipeline_region")+"" +
				" where instr(','||node_codes||',',?)>0 )";
		try {
			return CM.getDao().get("", sql, new ModuleFeatureBeanRowWapper<NodePipeline>(NodePipeline.class), new Object[]{nodecode});
		} catch (DaoException e) {
			logger.error("根据节点编码获取通道信息", e);
			throw new DaoException("根据节点编码获取通道信息", e);
		}
	}
	
	/**
	 * 得到最小负载的通道信息
	 * @param nodecode
	 * @return
	 * @throws DaoException
	 */
	public NodePipeline getMinLoad(String nodecode)throws DaoException {
		NodePipeline nodePipeline=this.getNodePieline(nodecode);
		if (nodePipeline!=null) {
			return nodePipeline;
		}
		//查找一个
		String sql="select * from "+SI_TABLE("turbo_pipeline_region")+" where count=(select min(count) from "+SI_TABLE("turbo_pipeline_region")+")";
		List<PipelineRegion> list=CM.getDao().list("", sql, new ModuleFeatureBeanRowWapper<PipelineRegion>(PipelineRegion.class), new Object[]{});
		if (list==null || list.isEmpty()) {
	    	return nodePipelineDao.getLocalTlqPipline();
		}
		//把对应的信息 保存起来
		PipelineRegion region=list.get(0);
		this.updateBean(region, nodecode);
		return nodePipelineDao.get(region.getPipelineId());
	}
	
	private void updateBean(PipelineRegion region,String nodecode) throws DaoException{
		
		if (region.getNodecodes()==null || "".equals(region.getNodecodes())) {
			region.setNodecodes(nodecode);
		}else{
			region.setNodecodes(region.getNodecodes()+","+nodecode);
		}
	    region.setCount(region.getCount()+1);
	    this.update(region);
	   //更新成功后，放到缓存
	   TlqCache.regionMap.put(nodecode, JsonUtil.toObject(nodePipelineDao.get(region.getPipelineId()).getParamStr(), PipeLineTlq.class).getBrokerIp());
	}
	
	/**
	 * 添加nodecode给某个通道，通过动态负载均衡
	 * @param nodecode
	 */
	public void insert(String nodecode) throws DaoException {
		//查找一个
		String sql="select * from "+SI_TABLE("turbo_pipeline_region")+" where count in (select min(count) from "+SI_TABLE("turbo_pipeline_region")+")";
		try {
			List<PipelineRegion> list=CM.getDao().list("", sql, new ModuleFeatureBeanRowWapper<PipelineRegion>(PipelineRegion.class), new Object[]{});
			
			if (list==null || list.isEmpty()) {
		    	return;
			}
			PipelineRegion region=list.get(0);
		   this.updateBean(region, nodecode);
		} catch (DaoException e) {
			logger.error("插入通道对应的节点编码信息时失败", e);
			throw new DaoException("插入通道对应的节点编码信息时失败", e);
		}
	}
	
	/**
	 * 根据队列信息获取通道对应的ip
	 * @return
	 */
	public String getManagedIP(String queue){
		if (!queue.contains("_TO_")) {//如果队列名称中不包含_TO_字符串，则说明就不是发送队列，直接返回当前tlq ip
			return  TlqConfig.TLQ_BROKER_IP;
		}
		//通过queue获取目的节点的的行政区编码 SQ_000000101_TO_020000101_SQL_DATA_LOG
		String nodecode=queue.split("_TO_")[1].substring(0,9);//以_TO_为分隔，取出目的节点的节点编码
		//通过行政区编码获取所对应的tlq ip
		String ip=TlqCache.regionMap.get(nodecode);
		if (ip ==null || "".equals(ip)) {//如果ip为空，从数据库中查询
			NodePipeline np;
			try {
				np = this.getNodePieline(nodecode);
				if (np!=null) {
					ip=JsonUtil.toObject(np.getParamStr(), PipeLineTlq.class).getBrokerIp();
					TlqCache.regionMap.put(nodecode, ip);
				}
			} catch (DaoException e) {
				logger.error("根据节点编码获取通道信息失败", e);
			}
		}
        if (ip ==null || "".equals(ip)) {//如果ip为空，取当前的tlq ip就行
        	ip=TlqConfig.TLQ_BROKER_IP;
        	TlqCache.regionMap.put(nodecode, ip);
		}
		return ip;
		
	}
	
}
